/**
  * 原生flow执行检查 => yarn flow
  * 原生flow-remove-types执行编译转换文件 => yarn low-remove-types src -d dist
  * 利用babel执行编译转换文件，依赖@babel/cli，@babel/core，@babel/preset-flow => yarn babel src -d dist
  @flow
*/


function sum (a: number, b: number) {
  return a + b
}

sum(100, 100)
sum(20, 20)

// flow类型推断
function square (n) {
  return n * n
}

square(6)

// 类型注解
const num: number = 100 || NaN || Infinity
const str: string = 'foo'
const bool: boolean = true || false
const n: null = null
const undef: void = undefined
const sym: symbol = Symbol()

// 数组注解
const arr1: Array<number | string> = [1, 2, 3, '1']
const arr2: number[] = [1, 2, 3]
// 元组
const arr3: [string, number] = ['1', 2]

// 对象注解
const obj1: { foo: string, bar: number } = { foo: '1', bar: 1 }
const obj2: { foo?: string, bar: number } = { bar: 1 }
const obj3: { [string]: string | number } = {}
obj3.key1 = 1
obj3.key2 = '1'

// 函数注解
function foo (): void {}
function foo1 (callback: (string, number) => void) {
  callback('1', 1)
}
foo1(function (s, n) {
  return undefined
})

// 特殊注解
const a: 'foo' = 'foo' // 字面量
const status: 'success' | 'warning' | 'danger' = 'success'
type StringOrNumber = string | number
const b: StringOrNumber = 1
const gender: ?number = undefined // 数字或未定义
const gender1: number | null | void = null

// 任意类型
// mixed会在编译阶段报错
function passMixed (value: mixed) {
  // 需要明确数据类型
  if (typeof value === 'string') {
    value.substr(0)
  }
  if (typeof value === 'number') {
    value * value
  }
}
passMixed('1000')
passMixed(1000)
// any只会在运行阶段报错，尽量不使用
function passAny (value: any) {
  value.substr(0)
  value * value
}
passAny('1000')
passAny(1000)

// 运行环境api自带注解
const element: HTMLElement | null = document.getElementById('1')
